package cn.iocoder.an.module.business.service.audittype;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.module.business.dal.dataobject.auditlevel.AuditLevelDO;
import cn.iocoder.an.module.business.dal.mysql.auditlevel.AuditLevelMapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.an.module.business.controller.admin.audittype.vo.*;
import cn.iocoder.an.module.business.dal.dataobject.audittype.AuditTypeDO;
import cn.iocoder.an.module.business.dal.dataobject.audittype.AuditConfigDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.business.dal.mysql.audittype.AuditTypeMapper;
import cn.iocoder.an.module.business.dal.mysql.audittype.AuditConfigMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.business.enums.ErrorCodeConstants.*;

/**
 * 审核类型配置 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class AuditTypeServiceImpl implements AuditTypeService {

    @Resource
    private AuditTypeMapper auditTypeMapper;
    @Resource
    private AuditConfigMapper auditConfigMapper;

    @Resource
    private AuditLevelMapper auditLevelMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createAuditType(AuditTypeSaveReqVO createReqVO) {
        // 插入
        AuditTypeDO auditType = BeanUtils.toBean(createReqVO, AuditTypeDO.class);
        auditTypeMapper.insert(auditType);


        // 插入子表
        createAuditConfigList(auditType.getId(), createReqVO.getAuditConfigs());
        // 返回
        return auditType.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAuditType(AuditTypeSaveReqVO updateReqVO) {
        // 校验存在
        validateAuditTypeExists(updateReqVO.getId());
        // 更新
        AuditTypeDO updateObj = BeanUtils.toBean(updateReqVO, AuditTypeDO.class);
        auditTypeMapper.updateById(updateObj);

        // 更新子表
        updateAuditConfigList(updateReqVO.getId(), updateReqVO.getAuditConfigs());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAuditType(Long id) {
        // 校验存在
        validateAuditTypeExists(id);
        // 删除
        auditTypeMapper.deleteById(id);

        // 删除子表
        deleteAuditConfigByAuditTypeId(id);
    }

    @Override
        @Transactional(rollbackFor = Exception.class)
    public void deleteAuditTypeListByIds(List<Long> ids) {
        // 删除
        auditTypeMapper.deleteByIds(ids);
    
    // 删除子表
            deleteAuditConfigByAuditTypeIds(ids);
    }


    private void validateAuditTypeExists(Long id) {
        if (auditTypeMapper.selectById(id) == null) {
            throw exception(AUDIT_TYPE_NOT_EXISTS);
        }
    }

    @Override
    public AuditTypeDO getAuditType(Long id) {
        return auditTypeMapper.selectById(id);
    }

    @Override
    public PageResult<AuditTypeDO> getAuditTypePage(AuditTypePageReqVO pageReqVO) {
        return auditTypeMapper.selectPage(pageReqVO);
    }

    @Override
    public List<AuditTypeDO> getAuditTypeList() {
        return auditTypeMapper.selectList();
    }

    // ==================== 子表（审核项） ====================

    @Override
    public List<AuditConfigDO> getAuditConfigListByAuditTypeId(Long auditTypeId) {
        return auditConfigMapper.selectListByAuditTypeId(auditTypeId);
    }

    @Override
    public List<AuditConfigDO> getAuditConfigListByAuditTypeIdWait(Long auditTypeId,Long levelId) {
        AuditLevelDO auditLevelDO = auditLevelMapper.selectById(levelId);
        List<Long> configId = auditLevelDO.getConfigId() != null ? auditLevelDO.getConfigId() : new ArrayList<>();
        configId.add(0L);
        LambdaQueryWrapperX<AuditConfigDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(AuditConfigDO::getAuditTypeId, auditTypeId);
        queryWrapperX.notIn(AuditConfigDO::getId, configId);

        return auditConfigMapper.selectList(queryWrapperX);
    }

    private void createAuditConfigList(Long auditTypeId, List<AuditConfigDO> list) {
        list.forEach(o -> o.setAuditTypeId(auditTypeId).clean());
        auditConfigMapper.insertBatch(list);
    }

    private void updateAuditConfigList(Long auditTypeId, List<AuditConfigDO> list) {
	    list.forEach(o -> o.setAuditTypeId(auditTypeId).clean());
	    List<AuditConfigDO> oldList = auditConfigMapper.selectListByAuditTypeId(auditTypeId);
	    List<List<AuditConfigDO>> diffList = diffList(oldList, list, (oldVal, newVal) -> {
            boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId());
            if (same) {
                newVal.setId(oldVal.getId()).clean(); // 解决更新情况下：updateTime 不更新
            }
            return same;
	    });

	    // 第二步，批量添加、修改、删除
	    if (CollUtil.isNotEmpty(diffList.get(0))) {
	        auditConfigMapper.insertBatch(diffList.get(0));
	    }
	    if (CollUtil.isNotEmpty(diffList.get(1))) {
	        auditConfigMapper.updateBatch(diffList.get(1));
	    }
	    if (CollUtil.isNotEmpty(diffList.get(2))) {
	        auditConfigMapper.deleteByIds(convertList(diffList.get(2), AuditConfigDO::getId));
	    }
    }

    private void deleteAuditConfigByAuditTypeId(Long auditTypeId) {
        auditConfigMapper.deleteByAuditTypeId(auditTypeId);
    }

	private void deleteAuditConfigByAuditTypeIds(List<Long> auditTypeIds) {
        auditConfigMapper.deleteByAuditTypeIds(auditTypeIds);
	}

}